<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body></body>
  <script>
    // console
    const PENDING = 'pending'
    const FULFILLED = 'fulfilled'
    const REJECTED = 'rejected'

    class MyPromise {
      constructor(fn) {
        fn(this.resolve, this.reject)
      }
      status = PENDING
      value = null
      errReson = null
      onFulfilledCallback = []
      onRejectedCallback = []
      resolve = (val) => {
        if (this.status === PENDING) {
          this.status = FULFILLED
          this.value = val
          while (this.onFulfilledCallback.length) {
            const fn = this.onFulfilledCallback.shift()
            console.log('fn==', fn)
            const tt = fn(val)
            console.log('tt==', tt)
          }
        }
      }
      reject = (err) => {
        if (this.status === PENDING) {
          this.status = REJECTED
          this.errReson = err
          while (this.onRejectedCallback.length) {
            this.onRejectedCallback.shift()(err)
          }
        }
      }
      then(onFulfilled, onRejected) {
        const promise2 = new MyPromise((resolve, reject) => {
          if (this.status === FULFILLED) {
            queueMicrotask(() => {
              const x = onFulfilled(this.value)
              console.log('xxx==', x)
              resolvePromise(promise2, x, resolve, reject)
            })
          } else if (this.status === REJECTED) {
            onRejected(this.errReson)
          } else if (this.status === PENDING) {
            this.onFulfilledCallback.push(onFulfilled)
            this.onRejectedCallback.push(onRejected)
          }
        })
        return promise2
      }
    }

    function resolvePromise(promise2, x, resolve, reject) {
      if (promise2 === x) {
        return reject(
          new TypeError('Chaining cycle detected for promise #<Promise>')
        )
      }
      if (x instanceof MyPromise) {
        x.then(resolve, reject)
      } else {
        resolve(x)
      }
    }

    const promise = new MyPromise((resolve, reject) => {
      resolve('success')
    })
    const p2 = function () {
      return new MyPromise((resolve, reject) => {
        resolve('other')
      })
    }

    const pp2 = promise.then(
      (value) => {
        console.log('promise', 1)
        console.log('resolve', value)
        return pp2
      },
      (reason) => {
        console.log('reject', reason)
      }
    )
    pp2.then(
      (res) => console.log('22', res),
      (reason) => {
        console.log(3)
        console.log(reason.message)
      }
    )

    // const promise1 = new Promise((resolve, reject) => {
    //   setTimeout(() => {
    //     resolve('success')
    //   }, 2000)
    // })
    // promise1.then((value) => {
    //   console.log('resolve==1', value)
    // })
    // promise1.then((value) => {
    //   console.log('resolve==2', value)
    // })
    // promise1.then((value) => {
    //   console.log('resolve==3', value)
    // })
  </script>
</html>
